Optimize the number of calls to fs::metadata
authorAlex Crichton <alex@alexcrichton.com>
Wed, 20 May 2015 06:04:47 +0000 (23:04 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 20 May 2015 06:04:47 +0000 (23:04 -0700)
When iterating over `DirEntry` values the file type of the entry can typically
be determined without a syscall, so use the new unstable APIs in `std::fs` to
avoid an extra call to `fs::metadata`. When traversing large directory trees the
improvement is quite noticeable!

src/cargo/lib.rs
src/cargo/ops/cargo_read_manifest.rs

index d2b01e92c93474840f1e7218ef473574460b6370..3a47f1eac5f5f2c5e838915a4a6371aec026a8f6 100644 (file)
@@ -1,5 +1,5 @@
 #![deny(unused)]
-#![feature(metadata_ext)]
+#![feature(metadata_ext, file_type, dir_entry_ext)]
 #![cfg_attr(test, deny(warnings))]
 
 #[cfg(test)] extern crate hamcrest;
index 2ac4e00211d00de510cbd5eed55286da77d9b107..c765e02c9275649240989ceb660579385b4f95b0 100644 (file)
@@ -73,13 +73,8 @@ pub fn read_packages(path: &Path, source_id: &SourceId, config: &Config)
     }
 }
 
-fn walk<F>(path: &Path, callback: &mut F) -> CargoResult<()>
-    where F: FnMut(&Path) -> CargoResult<bool>
-{
-    if !fs::metadata(&path).map(|m| m.is_dir()).unwrap_or(false) {
-        return Ok(())
-    }
-
+fn walk(path: &Path, callback: &mut FnMut(&Path) -> CargoResult<bool>)
+        -> CargoResult<()> {
     if !try!(callback(path)) {
         trace!("not processing {}", path.display());
         return Ok(())
@@ -95,8 +90,10 @@ fn walk<F>(path: &Path, callback: &mut F) -> CargoResult<()>
         Err(e) => return Err(From::from(e)),
     };
     for dir in dirs {
-        let dir = try!(dir).path();
-        try!(walk(&dir, callback));
+        let dir = try!(dir);
+        if try!(dir.file_type()).is_dir() {
+            try!(walk(&dir.path(), callback));
+        }
     }
     Ok(())
 }